home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 6 / QRZ Ham Radio Callsign Database - Volume 6.iso / pc / files / dsp / dspkgctr.z / dspkgctr / gcc / config / out-dsp56k.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-08  |  51.7 KB  |  2,504 lines

  1. /* subroutines for insn-output.c for motorola dsp56000/1
  2.    copyright ( c ) 1988 free software foundation, inc.
  3.  
  4.    $Id: out-dsp56k.c,v 1.43 91/12/02 15:52:43 jeff Exp $
  5.  
  6. this file is part of gnu cc.
  7.  
  8. gnu cc is distributed in the hope that it will be useful,
  9. but without any warranty.  no author or distributor
  10. accepts responsibility to anyone for the consequences of using it
  11. or for whether it serves any particular purpose or works at all,
  12. unless he says so in writing.  refer to the gnu cc general public
  13. license for full details.
  14.  
  15. everyone is granted permission to copy, modify and redistribute
  16. gnu cc, but only under the conditions described in the
  17. gnu cc general public license.     a copy of this license is
  18. supposed to have been given to you along with gnu cc so you
  19. can know your rights and responsibilities.  it should be in a
  20. file named copying.  among other things, the copyright notice
  21. and this notice must be preserved on all copies.  */
  22.  
  23.  
  24. #ifndef file
  25. #include <stdio.h>
  26. #endif
  27.  
  28. #include <string.h>
  29. #if defined ( _MSDOS )
  30. extern void *malloc( );
  31. #endif
  32.  
  33. #include <ctype.h>
  34.  
  35. #include "flags.h"
  36. #include "tree.h"
  37. #if ! defined( _INTELC32_ )
  38. #include "hard-reg-set.h"
  39. #else
  40. #include "hardrset.h"
  41. #endif
  42.  
  43. char mem_space = 'y';
  44. char memory_model = 'y';
  45.  
  46. func_attributes current_func_info = FUNC_NO_INFO;
  47.  
  48. static char local_call_used_regs[] = CALL_USED_REGISTERS;
  49. enum reg_class regno_reg_class ( );
  50.  
  51. int FirstSave;
  52.  
  53. void
  54. PushRegs ( file )
  55.     FILE* file;
  56. {
  57.     int reg_index;
  58.  
  59.     FirstSave = -1;
  60.     
  61.     for ( reg_index = 0; reg_index < FIRST_PSEUDO_REGISTER; ++ reg_index )
  62.     {
  63.     if ( regs_ever_live[ reg_index ] && 
  64.         ! local_call_used_regs[ reg_index ] )
  65.     {
  66.         if ( 0 > FirstSave )
  67.         {
  68.         FirstSave = reg_index;
  69.         }
  70.         
  71.         if ( DST_REGS == REGNO_REG_CLASS ( reg_index ))
  72.         {
  73.         if ( 'l' == memory_model )
  74.         {
  75.             fprintf ( file, "\
  76.     move    %c10,l:(r6)+\n", *reg_names[ reg_index ] );
  77.         }
  78.         else
  79.         {
  80.             fprintf ( file, "\
  81.     move    %s0,%c:(r6)+\n\
  82.     move    %s1,%c:(r6)+\n", reg_names[ reg_index ], mem_space,
  83.                  reg_names[ reg_index ], mem_space );
  84.         }
  85.         
  86.         }
  87.         else if ( SRC_REGS == REGNO_REG_CLASS ( reg_index ) ||
  88.              MPY_REGS == REGNO_REG_CLASS ( reg_index ))
  89.         {
  90.         if ( 'l' == memory_model )
  91.         {
  92.             /* try to save x or y as a pair. */
  93.             if ( reg_index & 1 )
  94.             {
  95.             /* x1 or y1 */
  96.             if ( ! ( regs_ever_live[ reg_index - 1 ] &&
  97.                 ! local_call_used_regs[ reg_index - 1 ] ))
  98.             {
  99.                 /* was the 0 portion saved ? if so, then we
  100.                    don't need to do anything, else save the 1 ! */
  101.  
  102.                 fprintf ( file, "\
  103.     move    %s,%c:(r6)+\n", reg_names[ reg_index ], mem_space );
  104.             }
  105.             }
  106.             else
  107.             {
  108.             /* x0 or y0 */
  109.             if ( regs_ever_live[ reg_index + 1 ] && 
  110.                 ! local_call_used_regs[ reg_index + 1 ] )
  111.             {
  112.                 /* are we also saving the 1 portion ? if so,
  113.                    save the 1 as well as the 0 with an l: move.
  114.                    otherwise, just save the 0. */
  115.                 fprintf ( file, "\
  116.     move    %c,l:(r6)+\n", *reg_names[ reg_index ] );
  117.             }
  118.             else
  119.             {
  120.                 fprintf ( file, "\
  121.     move    %s,%c:(r6)+\n", reg_names[ reg_index ], mem_space );
  122.             }
  123.             }
  124.         }
  125.         else
  126.         {
  127.             fprintf ( file, "\
  128.     move    %s,%c:(r6)+\n", reg_names[ reg_index ], mem_space );
  129.         }
  130.         }
  131.         else
  132.         {
  133.         fprintf ( file, "\
  134.     move    %s,%c:(r6)+\n", reg_names[ reg_index ], mem_space );
  135.         }
  136.         
  137.     }
  138.     }
  139. }
  140.  
  141. void
  142. PopRegs ( file )
  143.     FILE* file;
  144. {
  145.     int reg_index = FIRST_PSEUDO_REGISTER;
  146.     int first_save = 0;
  147.     
  148. #define SAVE_CHECK \
  149. {\
  150.     if ( ! first_save )\
  151.     {\
  152.     first_save = 1;\
  153.     fprintf ( file, "\tmove    (r6)-\n" );\
  154.     }\
  155. }
  156.  
  157.  
  158.     while ( -- reg_index >= 0 )
  159.     {
  160.     if ( regs_ever_live[ reg_index ] && 
  161.         ! local_call_used_regs[ reg_index ] )
  162.     {
  163.         SAVE_CHECK;
  164.         
  165.         if ( DST_REGS == REGNO_REG_CLASS ( reg_index ))
  166.         {
  167.         if ( reg_index == FirstSave )
  168.         {
  169.             if ( 'l' == memory_model )
  170.             {
  171.             fprintf ( file, "\
  172.     move    l:(r6),%c\n", *reg_names[ reg_index ] );
  173.             }
  174.             else
  175.             {
  176.             fprintf ( file, "\
  177.     move    %c:(r6)-,%s\n\
  178.     move    %c:(r6),%s0\n", mem_space, reg_names[ reg_index ],
  179.                  mem_space, reg_names[ reg_index ] );
  180.             }
  181.         }
  182.         else
  183.         {
  184.             if ( 'l' == memory_model )
  185.             {
  186.             fprintf ( file, "\
  187.     move    l:(r6)-,%c\n", *reg_names[ reg_index ] );
  188.             }
  189.             else
  190.             {
  191.             fprintf ( file, "\
  192.     move    %c:(r6)-,%s\n\
  193.     move    %c:(r6)-,%s0\n", mem_space, reg_names[ reg_index ],
  194.                  mem_space, reg_names[ reg_index ] );
  195.             }
  196.         }
  197.         }
  198.         else if ( SRC_REGS == REGNO_REG_CLASS ( reg_index ) ||
  199.              MPY_REGS == REGNO_REG_CLASS ( reg_index ))
  200.         {
  201.         if ( 'l' == memory_model )
  202.         {
  203.             if ( reg_index & 1 )
  204.             {
  205.             /* x1 or y1 */
  206.             if ( ! ( regs_ever_live[ reg_index -1 ] && 
  207.                 ! local_call_used_regs[ reg_index - 1 ] ))
  208.             {
  209.                 /* if the 0 portion wasn't saved we need to
  210.                    restore the 1, otherwise do nothing. */
  211.  
  212.                 if ( reg_index == FirstSave )
  213.                 {
  214.                 fprintf ( file, "\
  215.     move    %c:(r6),%s\n", mem_space, reg_names[ reg_index ] );
  216.                 }
  217.                 else
  218.                 {
  219.                 fprintf ( file, "\
  220.     move    %c:(r6)-,%s\n", mem_space, reg_names[ reg_index ] );
  221.                 }
  222.             }
  223.             }
  224.             else
  225.             {
  226.             /* x0 or y0 */
  227.             if ( regs_ever_live[ reg_index + 1 ] && 
  228.                 ! local_call_used_regs[ reg_index + 1 ] )
  229.             {
  230.                 /* if the 1 portion was also saved, then we
  231.                    need to to do an l: restore, otherwise a y:. */
  232.  
  233.                 if ( reg_index == FirstSave )
  234.                 {
  235.                 fprintf ( file, "\
  236.     move    l:(r6),%c\n", *reg_names[ reg_index ] );
  237.                 }
  238.                 else
  239.                 {
  240.                 fprintf ( file, "\
  241.     move    l:(r6)-,%c\n", *reg_names[ reg_index ] );
  242.                 }
  243.             }
  244.             else
  245.             {
  246.                 if ( reg_index == FirstSave )
  247.                 {
  248.                 fprintf ( file, "\
  249.     move    %c:(r6),%s\n", mem_space, reg_names[ reg_index ] );
  250.                 }
  251.                 else
  252.                 {
  253.                 fprintf ( file, "\
  254.     move    %c:(r6)-,%s\n", mem_space, reg_names[ reg_index ] );
  255.                 }
  256.             }
  257.             }
  258.         }
  259.         else
  260.         {
  261.             if ( reg_index == FirstSave )
  262.             {
  263.             fprintf ( file, "\
  264.     move    %c:(r6),%s\n", mem_space, reg_names[ reg_index ] );
  265.             }
  266.             else
  267.             {
  268.             fprintf ( file, "\
  269.     move    %c:(r6)-,%s\n", mem_space, reg_names[ reg_index ] );
  270.             }
  271.         }
  272.         }
  273.         else
  274.         {
  275.         if ( reg_index == FirstSave )
  276.         {
  277.             fprintf ( file, "\
  278.     move    %c:(r6),%s\n", mem_space, reg_names[ reg_index ] );
  279.         }
  280.         else
  281.         {
  282.             fprintf ( file, "\
  283.     move    %c:(r6)-,%s\n", mem_space, reg_names[ reg_index ] );
  284.         }
  285.         }
  286.     }
  287.     }
  288. }
  289.  
  290. int
  291. go_if_legitimate_address ( mode, x, strict )
  292.     int mode;
  293.     rtx x;
  294.     int strict;
  295. {
  296.     /* constant pointer */
  297.  
  298.     if ( CONSTANT_ADDRESS_P ( x ) )
  299.     {
  300.     return 1;
  301.     }
  302.  
  303.     /* note that REG_OK_STRICT may NOT be defined here! */
  304.     /* register pointer */
  305.  
  306.     if ( REG_P ( x ) && 
  307.     (( strict ) ? 
  308.      ( REGNO_OK_FOR_INDEX_P ( REGNO ( x ))) :
  309.      ( REG_OK_FOR_INDEX_P ( x ))))
  310.     {
  311.     return 1;
  312.     }
  313.     
  314.     /* register arithmetic */
  315.     
  316.     switch ( GET_CODE ( x ) )
  317.     {
  318.     case SUBREG:
  319.     return go_if_legitimate_address ( mode, XEXP ( x, 0 ), strict );
  320.                      
  321.     case POST_DEC:
  322.     case POST_INC:
  323.     case PRE_INC:
  324.     case PRE_DEC:
  325.     if ( REG_P ( XEXP ( x, 0 )) && 
  326.         (( strict ) ? 
  327.          ( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 0 )))) :
  328.          ( REG_OK_FOR_INDEX_P ( XEXP ( x, 0 )))))
  329.     {
  330.         return 1;
  331.     }
  332.     break;
  333.     
  334.     case PLUS:
  335.     if ( REG_P ( XEXP ( x, 0 )) && 
  336.         ( Pmode == GET_MODE ( XEXP ( x, 0 ))) &&
  337.         ( CONST_INT == GET_CODE ( XEXP ( x, 1 ))) &&
  338.         (( strict ) ? 
  339.          ( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 0 )))) :
  340.          ( REG_OK_FOR_INDEX_P ( XEXP ( x, 0 )))))
  341.     {
  342.         return 1;
  343.     }
  344.  
  345.     if ( REG_P ( XEXP ( x, 1 )) && 
  346.         ( Pmode == GET_MODE ( XEXP ( x, 1 ))) &&
  347.         ( CONST_INT == GET_CODE ( XEXP ( x, 0 ))) &&
  348.         (( strict ) ? 
  349.          ( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 1 )))) :
  350.          ( REG_OK_FOR_INDEX_P ( XEXP ( x, 1 )))))
  351.     {
  352.         return 1;
  353.     }
  354.     }
  355.     return 0;
  356. }
  357.  
  358. void
  359. print_operand_address ( file, addr )
  360.     FILE* file;
  361.     rtx addr;
  362. {
  363.     register rtx reg0;
  364.     register rtx reg1;
  365.  
  366.     switch ( GET_CODE ( addr ) )
  367.     {
  368.  
  369.     case REG:
  370.     fprintf ( file, "(%s)", reg_names[ REGNO ( addr )] );
  371.     break;
  372.  
  373.     case POST_INC:
  374.     fprintf ( file, "(%s)+", reg_names[ REGNO ( XEXP ( addr, 0 ) )] );
  375.     break;
  376.  
  377.     case POST_DEC:
  378.     fprintf ( file, "(%s)-", reg_names[ REGNO ( XEXP ( addr, 0 ) )] );
  379.     break;
  380.  
  381.     case PLUS:
  382.     abort ( );
  383.     
  384.     default:
  385.     output_addr_const ( file, addr );
  386.     }
  387. }
  388.  
  389. void
  390. notice_update_cc ( exp, insn )
  391.     rtx exp;
  392.     rtx insn;
  393. {
  394.     if ( PARALLEL == GET_CODE ( exp ))
  395.     {
  396.     rtx call_insn = XVECEXP ( exp, 0, 0 );
  397.     if ( GET_CODE ( call_insn ) == SET &&
  398.          GET_CODE ( XEXP ( call_insn, 1 )) == CALL )
  399.     {
  400.         cc_status.flags = 0;
  401.         cc_status.value1 = cc0_rtx;
  402.         cc_status.value2 = gen_rtx ( REG, SImode, DSP56_A_REGNUM );
  403.         cc_status.mdep = CC_SIGNED;
  404.     }
  405.     else
  406.     {
  407.         CC_STATUS_INIT;
  408.     }
  409.     }
  410.     else if ( SET == GET_CODE ( exp ))
  411.     {
  412.     switch ( GET_CODE ( SET_DEST ( exp )))
  413.     {
  414.     case CC0:
  415.         cc_status.flags = 0;
  416.         cc_status.value1 = SET_DEST ( exp );
  417.         cc_status.value2 = SET_SRC ( exp );
  418.         break;
  419.         
  420.     case REG:
  421.         CC_STATUS_INIT;
  422.     }
  423.     }
  424.     else
  425.     {
  426.     CC_STATUS_INIT;
  427.     }
  428. }
  429.  
  430. rtx
  431. next_cc_relevancy ( insn )
  432.     rtx insn;
  433. {
  434.     rtx peek = NEXT_INSN ( insn );
  435.     
  436.     for ( ; NULL != peek; peek = NEXT_INSN ( peek ))
  437.     {
  438.     switch ( GET_CODE( peek ))
  439.     {
  440.     case JUMP_INSN:
  441.     case CALL_INSN:
  442.     case CODE_LABEL:
  443.     case BARRIER:
  444.         return peek;
  445.         
  446.     case INSN:
  447.         if (( PARALLEL == GET_CODE ( PATTERN ( peek ))) &&
  448.         ( SET == GET_CODE ( XVECEXP ( PATTERN ( peek ), 0, 0 ))) &&
  449.         ( 0 == strcmp ( GET_RTX_FORMAT ( GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ))), "ee" )) &&
  450.         ( cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 0 )))
  451.         {
  452.         return peek;
  453.         }
  454.     }
  455.     }
  456.     return insn;
  457. }
  458.  
  459. enum mdep_cc_info
  460. next_cc_use ( insn )
  461.     rtx insn;
  462. {
  463.     enum rtx_code jump_code;
  464.     rtx peek = NEXT_INSN ( insn );
  465.     
  466.     for ( ; NULL != peek; peek = NEXT_INSN ( peek ))
  467.     {
  468.     if ( JUMP_INSN == GET_CODE ( peek ))
  469.     {
  470.         break;
  471.     }
  472.     if ( CALL_INSN == GET_CODE ( peek ) ||
  473.         CODE_LABEL == GET_CODE ( peek ) ||
  474.         BARRIER == GET_CODE ( peek ) )
  475.     {
  476.         return CC_UNKNOWN;
  477.     }
  478.     if ( INSN == GET_CODE ( peek ) &&
  479.         PARALLEL == GET_CODE ( PATTERN ( peek )) &&
  480.         SET == GET_CODE ( XVECEXP ( PATTERN ( peek ), 0, 0 )) &&
  481.         0 == strcmp ( GET_RTX_FORMAT ( GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ))), "ee" ) &&
  482.         ( cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 0 ) ||
  483.          cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 1 )))
  484.     {
  485.         jump_code = GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ));
  486.         
  487.         if ( GEU == jump_code || GTU == jump_code || LEU == jump_code
  488.         || LTU == jump_code )
  489.         {
  490.         return CC_UNSIGNED;
  491.         }
  492.         else
  493.         {
  494.         return CC_SIGNED;
  495.         }
  496.     }
  497.     }
  498.  
  499.     if (( NULL == peek ) || 
  500.     ( JUMP_INSN != GET_CODE ( peek )) ||
  501.     ( SET != GET_CODE ( PATTERN ( peek ))) ||
  502.     ( IF_THEN_ELSE != GET_CODE ( XEXP ( PATTERN ( peek ), 1 ))))
  503.     {
  504.     return CC_UNKNOWN;
  505.     }
  506.     jump_code = GET_CODE ( XEXP ( XEXP ( PATTERN ( peek ), 1 ), 0 ));
  507.     
  508.     if ( GEU == jump_code || GTU == jump_code || LEU == jump_code
  509.     || LTU == jump_code || EQU == jump_code || NEU == jump_code )
  510.     {
  511.     return CC_UNSIGNED;
  512.     }
  513.     else
  514.     {
  515.     return CC_SIGNED;
  516.     }
  517. }
  518.  
  519. /* hard_regno_mode_ok -
  520.  * this global function implements the tm-m56k.h file macro of the same name.
  521.  * a 1 is returned if regno can be used to hold a value of type mode.
  522.  */
  523.  
  524. int
  525. hard_regno_mode_ok ( regno, mode )
  526.     int regno;
  527.     int mode;
  528. {
  529.     switch ( mode )
  530.     {
  531.     case VOIDmode:
  532.     return 1;
  533.     
  534.     case SFmode:
  535.     case DFmode:
  536.     case DImode:
  537.     /* for doubles, floats, and longs, we need 48-bit registers. */
  538.     if ( DSP56_X0_REGNUM == regno || DSP56_Y0_REGNUM == regno ||
  539.         DSP56_A_REGNUM == regno || DSP56_B_REGNUM == regno )
  540.     {
  541.         return 1;
  542.     }
  543.     else
  544.     {
  545.         return 0;
  546.     }
  547.     break;
  548.  
  549.     case PSImode:
  550.     /* for pointers we can use any register. */
  551.     return 1;
  552.     
  553.     default:
  554.     /* for all other cases, we assume that a 24-bit reg is needed. */
  555.     if ( regno < 6 )
  556.     {
  557.         return 1;
  558.     }
  559.     else
  560.     {
  561.         return 0;
  562.     }
  563.     break;
  564.     }
  565. }
  566.  
  567. /* modes_tieable_p -
  568.  * this global function implements the tm-m56k.h file macro of the same name.
  569.  * a 1 is returned if both modes can always use the same pseudo register.
  570.  */
  571.  
  572. int
  573. modes_tieable_p ( mode1, mode2 )
  574.     int mode1;
  575.     int mode2;
  576. {
  577.     if ( mode1 == mode2 )
  578.     {
  579.     return 1;
  580.     }
  581.     
  582.     switch ( mode1 )
  583.     {
  584.     case SFmode:
  585.     case DFmode:
  586.     case DImode:
  587.     if ( SFmode == mode2 || DFmode == mode2 || DImode == mode2 )
  588.     {
  589.         return 1;
  590.     }
  591.     else
  592.     {
  593.         return 0;
  594.     }
  595.     break;
  596.     }
  597.     return 0;
  598. }
  599.  
  600. /* regno_reg_class -
  601.  * this global function implements the tm-m56k.h file macro of the same name.
  602.  * the class number of the smallest class containing reg number regno is
  603.  * returned.
  604.  */
  605.  
  606. enum reg_class
  607. regno_reg_class ( regno )
  608.     int regno;
  609. {
  610.     switch ( regno )
  611.     {
  612.     case DSP56_X0_REGNUM:
  613.     case DSP56_Y0_REGNUM:
  614.     return MPY_REGS;
  615.     
  616.     case DSP56_X1_REGNUM:
  617.     case DSP56_Y1_REGNUM:
  618.     return SRC_REGS;
  619.  
  620.     case DSP56_A_REGNUM:
  621.     case DSP56_B_REGNUM:
  622.     return DST_REGS;
  623.  
  624.     default:
  625.     if ( regno < 14 )
  626.     {
  627.         return ADDR_REGS;
  628.     }
  629.     return ALL_REGS;
  630.     }
  631. }
  632.  
  633.  
  634. /* reg_class_from_letter -
  635.  * this global function implements the tm-m56k.h file macro of the same name.
  636.  * the class number of the given letter is returned.
  637.  */
  638.  
  639. enum reg_class
  640. reg_class_from_letter ( c )
  641.     char c;
  642. {
  643.     switch ( c )
  644.     {
  645.     case 'S':
  646.     return SRC_REGS;
  647.     case 'D':
  648.     return DST_REGS;
  649.     case 'A':
  650.     return ADDR_REGS;
  651.     case 'R':
  652.     return MPY_REGS;
  653.     
  654.     default:
  655.     return NO_REGS;
  656.     }
  657. }
  658.  
  659. /* reg_class_from_letter -
  660.  * this global function implements the tm-m56k.h file macro of the same name.
  661.  * the max number of consecutive registers needed per mode is returned.
  662.  */
  663.  
  664. int
  665. class_max_nregs ( class, mode )
  666.     int class;
  667.     int mode;
  668. {
  669.     if (( SFmode == mode || DFmode == mode || DImode == mode ) &&
  670.     ( SRC_REGS == class ))
  671.     {
  672.     return 2;
  673.     }
  674.     else
  675.     {
  676.     return 1;
  677.     }
  678. }
  679.  
  680. /* ---------------------------------------------------------------- *\
  681.    
  682.    name         dgetmant
  683.  
  684.    synopsis     dgetmant(dfptval, wordnum)
  685.                 double dfptval;
  686.         int wordnum;
  687.  
  688.    description
  689.       Inputs:
  690.          dfptval = double precision value from which mantissa is extracted
  691.          wordnum:  0 = upper 20 bits (leading 1 suppressed)
  692.          1 = lower 32 bits
  693.  
  694.    return value 
  695.  
  696. \* ---------------------------------------------------------------- */
  697.  
  698. long dgetmant(dfptval, wordnum)
  699. double dfptval;
  700. int    wordnum;
  701. {
  702.    long *ivalptr;
  703.  
  704.    ivalptr = (long *) &dfptval;
  705.  
  706. #if defined( _MSDOS ) || defined( MIPSEL )
  707.    if (wordnum == 0)
  708.       return( ((*(ivalptr+1))) & 0x000fffffL);
  709.    else   /* lower word */
  710.       return( *(ivalptr) );
  711. #else
  712.    if (wordnum == 0)
  713.       return( ((*ivalptr)) & 0x000fffff);
  714.    else   /* lower word */
  715.       return( *(ivalptr+1) );
  716. #endif
  717. }
  718.  
  719.  
  720.  
  721. long dgetexp(dfptval)
  722. double dfptval;
  723. {
  724.    long *ivalptr;
  725.  
  726.    ivalptr = (long *) &dfptval;
  727. #if defined( _MSDOS ) || defined( MIPSEL )
  728.    ivalptr++;
  729. #endif
  730.    return( ((*ivalptr)>>20) & 0x07ff );       /* masks sign bit too */
  731. }
  732.  
  733. union real_extract adjusted_dval;
  734.  
  735. void
  736. dtok ( file, davey )
  737.     FILE* file;
  738.     double davey;
  739. {
  740.     union real_extract dval;
  741.     unsigned long   L_word, H_word, tmp, tmp2, dsgn;
  742.     long   increase_exponent;
  743.     
  744.     dval.d = davey;
  745.  
  746.     if ( dval.d == 0 )
  747.     {
  748.     H_word = L_word = 0;
  749.     }
  750.     else
  751.     {
  752.     L_word = dgetexp(dval.d);       /* ieee exponent */
  753.     H_word = dgetmant(dval.d,0);    /* grab upper 20 bits of double */
  754.     tmp2=dgetmant(dval.d,1);        /* lower 32 bits of ieee mantissa */
  755.  
  756.     /* ieee denormalized number */
  757.     if ( L_word == 0 )
  758.     {
  759.         L_word++; /* try it*/
  760.  
  761.         /* normalize it */        
  762.         while ( ! ( H_word & 0x100000 ) )
  763.         {
  764.         L_word -- ;      /* exponent decreases */
  765.         H_word <<= 1 ;   /* shift entire 52 bit ieee mantissa left */
  766.         
  767.         if ( tmp2 & 0x80000000l )
  768.         {
  769.             H_word |= 1 ;
  770.         }
  771.            
  772.         tmp2 <<= 1 ;
  773.         }
  774.     }
  775.  
  776.     /* normalized ieee number with implied leading 1 */
  777.     else
  778.     {
  779.         H_word |= 0x00100000;      /* add leading 1 */
  780.     }
  781.        
  782.     H_word <<= 10;
  783.     tmp = ((tmp2 & 0xc0000000) >> 1);   /* grab lower 2 bits */
  784.     tmp >>= 21;                         /* ------------------- */
  785.     H_word |= tmp;                      /* combine upper and lower */
  786.     increase_exponent=0;
  787.  
  788.     /* round up for 1/2 lsb of kp mantissa */
  789.     if ( tmp2 & 0x20000000l )
  790.     {
  791.         if ( H_word >= 0x7fffff00 )
  792.         {
  793.         increase_exponent = 1;
  794.         H_word += 0x100;
  795.         H_word >>= 1;
  796.         }
  797.         
  798.         else
  799.         {
  800.         H_word += 0x100;
  801.         }
  802.     }
  803.  
  804.  
  805. #if defined( _MSDOS ) || defined( MIPSEL )
  806.     dsgn = ( * (long *) &(dval.i[1]) ) & 0x80000000l;
  807. #else   /* real computers */
  808.     dsgn = ( * (long *) &(dval.i[0]) ) & 0x80000000l;
  809. #endif
  810.  
  811.     /* check for negative value in ieee format */
  812.     if ( dsgn )
  813.     {
  814.         H_word = -H_word;
  815.     }  
  816.        
  817.     H_word >>= 8;
  818.     L_word -= 1023;             /* IEEE double precision bias  */
  819.     L_word += 8191;             /* kevFP little precision bias */
  820.     L_word ++;                  /* lameFP s.xxx..xx */
  821.     L_word += increase_exponent; /* in case rounding modified exponent */
  822.     
  823.     /* negative weird case ( -0.5 == 800000  not c00000 ) */
  824.     if ( (H_word & 0x800000) && (H_word & 0x400000) )
  825.     {
  826.         H_word <<= 1;
  827.         L_word--;
  828.     }  
  829.     }
  830.    
  831.     
  832.     if ( NULL != file )
  833.     {
  834.     if ( 'l' == memory_model )
  835.     {
  836.         fprintf ( file, "\tdc\t$%06x%06x\n", H_word & 0xffffff,
  837.              L_word & 0xffffff );
  838.     }
  839.     else
  840.     {
  841.         fprintf ( file, "\tdc\t$%06x\n\tdc\t$%06x\n", L_word & 0xffffff,
  842.              H_word & 0xffffff );
  843.     }
  844.     }
  845.     
  846.     adjusted_dval.i[1] = ( 0x00ffffff & H_word );
  847.     adjusted_dval.i[0] = ( 0x00ffffff & L_word );
  848. }
  849.  
  850.  
  851. int
  852. local_first_parm_offset ( fundecl ) 
  853.     tree fundecl;
  854. {
  855.     tree arg_list;
  856.     
  857. #if 0
  858.     if (( NULL == fundecl ) ||
  859.     ( NULL == ( arg_list = DECL_ARGUMENTS ( fundecl ))))
  860.     {
  861.     return -4;
  862.     }
  863.     
  864.     return - int_size_in_bytes ( DECL_ARG_TYPE ( arg_list )) + -3;
  865. #else
  866.     return -2;
  867. #endif    
  868. }
  869.  
  870. void
  871. print_operand ( file, x, code )
  872.     FILE* file;
  873.     rtx x;
  874.     char code;
  875. {
  876.     rtx ensure_pointer_result_size ( );
  877.     rtx ensure_integer_result_size ( );
  878.     
  879.     if ( 'p' == code )
  880.     {
  881.     x = ensure_pointer_result_size ( copy_rtx ( x ));
  882.  
  883.     output_addr_const ( file, x );
  884.     return;
  885.     }
  886.     else if ( 'q' == code )
  887.     {
  888.     x = ensure_integer_result_size ( copy_rtx ( x ));
  889.  
  890.     output_addr_const ( file, x );
  891.     return;
  892.     }
  893.     
  894.     switch ( GET_CODE ( x ) )
  895.     {
  896.     case REG:
  897.     switch ( code )
  898.     {
  899.     case 'd':
  900.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
  901.         break;
  902.         
  903.     case 'e':
  904.         if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( x )))
  905.         {
  906.         if ( MEM_IN_STRUCT_P ( x ))
  907.         {
  908.             /* see comment in final.c */
  909.             fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
  910.         }
  911.         else
  912.         {
  913.             fprintf ( file, "%s1", reg_names[ REGNO ( x ) ] );
  914.         }
  915.         }
  916.         else
  917.         {
  918.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
  919.         }
  920.         break;
  921.         
  922.     case 'g':
  923.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ^ 1 ] );
  924.         break;
  925.         
  926.     case 'h':
  927.         fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
  928.         break;
  929.  
  930.     case 'i':
  931.         fprintf ( file, "%c", *( reg_names[ REGNO ( x ) ] ));
  932.         break;
  933.  
  934.     case 'j':
  935.         fprintf ( file, "n%c", * ( reg_names[ REGNO ( x ) ] + 1 ));
  936.         break;
  937.         
  938.     case 'k':
  939.         fprintf ( file, "%s2", reg_names[ REGNO ( x ) ] );
  940.         break;
  941.         
  942.     case 'm':
  943.         fprintf ( file, "%c", (reg_names[ REGNO ( x ) ])[0] );
  944.         break;
  945.         
  946.     case 'o':
  947.         fprintf ( file, "%c10", (reg_names[ REGNO ( x ) ])[0] );
  948.         break;
  949.         
  950.     default:
  951.         if ( MEM_IN_STRUCT_P ( x ))
  952.         {
  953.         /* see comment in final.c */
  954.         fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
  955.         }
  956.         else
  957.         {
  958.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
  959.         }
  960.         break;
  961.     }
  962.     break;
  963.     
  964.     case MEM:
  965.     switch ( code )
  966.     {
  967.     case 'f':
  968.         /* print out a 'l' instead of an x or y when we need to */
  969.         if (( 'l' == memory_model ) && 
  970.         (( DImode == GET_MODE ( x )) ||
  971.          ( SFmode == GET_MODE ( x )) ||
  972.          ( DFmode == GET_MODE ( x ))))
  973.         {
  974.         fprintf ( file, "l:" );
  975.         }
  976.         else
  977.         {
  978.         fprintf ( file, "%c:", mem_space );
  979.         }
  980.         output_address ( ensure_pointer_result_size 
  981.                 ( copy_rtx ( XEXP ( x, 0 ))));
  982.         break;
  983.         
  984.     default:
  985.         output_address ( ensure_pointer_result_size 
  986.                 ( copy_rtx ( XEXP ( x, 0 ))));
  987.     }
  988.     return;
  989.  
  990.     case CONST_INT:
  991.     if ( 0 == ( INTVAL ( x ) >> 8 ))
  992.     {
  993.         fprintf ( file, "#>$%02x", INTVAL ( x ) );
  994.     }
  995.     else
  996.     {
  997.         fprintf ( file, "#>$%06x", INTVAL ( x ) );
  998.     }
  999.     return;
  1000.  
  1001.     default:
  1002. #if 0
  1003.     fprintf ( file, "#" );
  1004.     if ( CONSTANT_ADDRESS_P ( x ))
  1005.     {
  1006.         output_addr_const ( file, x );
  1007.     }
  1008.     else
  1009.     {
  1010.         output_operand ( x, 'c' );
  1011.     }
  1012. #endif
  1013.     abort ( );
  1014.     }
  1015. }
  1016.  
  1017. void
  1018. simplify_cse_victims ( first )
  1019.     rtx first;
  1020. {
  1021.     rtx point, elem;
  1022.     
  1023.     while ( first )
  1024.     {
  1025.     /* is it a 3 element PARALLEL ? */
  1026.     if (( INSN == GET_CODE ( first )) &&
  1027.         ( point = PATTERN ( first ), PARALLEL == GET_CODE ( point )) &&
  1028.         ( 3 == XVECLEN ( point, 0 )) &&
  1029.  
  1030.         /* is the 1st element a ( SET ( REG ) ( REG / CONST_INT )) ? */
  1031.         ( elem = XVECEXP ( point, 0, 0 ), SET == GET_CODE ( elem )) &&
  1032.         ( REG == GET_CODE ( SET_DEST ( elem ))) &&
  1033.         (( REG == GET_CODE ( SET_SRC ( elem ))) ||
  1034.          ( CONST == GET_CODE ( SET_SRC ( elem ))) ||
  1035.          ( CONST_INT == GET_CODE ( SET_SRC ( elem )))) &&
  1036.  
  1037.         /* is the 2nd element a ( CLOBBER ( REG )) ? */
  1038.         ( elem = XVECEXP ( point, 0, 1 ), CLOBBER == GET_CODE ( elem )) &&
  1039.         ( REG == GET_CODE ( XEXP ( elem, 0 ))) &&
  1040.  
  1041.         /* is the 3rd element a ( CLOBBER ( REG )) ? */
  1042.         ( elem = XVECEXP ( point, 0, 2 ), CLOBBER == GET_CODE ( elem )) &&
  1043.         ( REG == GET_CODE ( XEXP ( elem, 0 ))))
  1044.     {
  1045.         /* we've got a blown-out div template ! substitute with a simple
  1046.            ( SET ( REG ) ( REG / CONST_INT )) (note: really the 1st 
  1047.            element of the parallel). */
  1048.  
  1049.         PATTERN ( first ) = XVECEXP ( point, 0, 0 );
  1050.     }
  1051.     first = NEXT_INSN ( first );
  1052.     }
  1053. }
  1054.  
  1055.  
  1056. static int
  1057. mpy_insn_p ( insn )
  1058.     rtx insn;
  1059. {
  1060.     return (( INSN == GET_CODE ( insn )) &&
  1061.         ( SET == GET_CODE ( PATTERN ( insn ))) &&
  1062.         ( REG == GET_CODE ( SET_DEST ( PATTERN ( insn )))) &&
  1063.         ( MULT == GET_CODE ( SET_SRC ( PATTERN ( insn )))));
  1064. }
  1065.  
  1066. static int
  1067. mac_insn_p ( insn )
  1068.     rtx insn;
  1069. {
  1070.     /* mac +/- shape detector. */
  1071.     return (( INSN == GET_CODE ( insn )) &&
  1072.         ( SET == GET_CODE ( PATTERN ( insn ))) &&
  1073.         ( REG == GET_CODE ( SET_DEST ( PATTERN ( insn )))) &&
  1074.         (( PLUS == GET_CODE ( SET_SRC ( PATTERN ( insn )))) ||
  1075.          ( MINUS == GET_CODE ( SET_SRC ( PATTERN ( insn ))))) &&
  1076.         (( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( insn )), 0 ))) ||
  1077.          ( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( insn )), 1 )))));
  1078. }
  1079.  
  1080. static rtx
  1081. mac_addative_input ( mac )
  1082.     rtx mac;
  1083. {
  1084.     return ( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( mac )), 0 ))) ?
  1085.     XEXP ( SET_SRC ( PATTERN ( mac )), 1 ) :
  1086.         XEXP ( SET_SRC ( PATTERN ( mac )), 0 );
  1087. }
  1088.  
  1089. void
  1090. reduce_norm_freq ( first )
  1091.     rtx first;
  1092. {
  1093.     /* point to the last insn.
  1094.        search up the list for each mac insn:
  1095.            detemine the addative_input.
  1096.        foreach insn in LOG_LINKS( point ):
  1097.            if insn SETs the addative_input, and insn is a mac or mpy, and
  1098.               there are no reload generated references to the operand
  1099.           between these two instructions, then:
  1100.                mark the pointed to mac as not needing input normalization
  1101.            mark the mpy/mac insn as not needing output normalization.
  1102.        
  1103.        the templates for mpy/mac will check for these flags. */
  1104.  
  1105.     rtx last = first, point;
  1106.     
  1107.     /* find the last insn, search up from it */
  1108.     while ( NULL != NEXT_INSN ( last ))
  1109.     {
  1110.     last = NEXT_INSN ( last );
  1111.     }
  1112.  
  1113.     while ( last != first )
  1114.     {
  1115.     if ( mac_insn_p ( last ))
  1116.     {
  1117.         rtx add_in = mac_addative_input ( last );
  1118.         rtx insn_chain = LOG_LINKS ( last );
  1119.         
  1120.         while ( NULL != insn_chain )
  1121.         {
  1122.         rtx this_insn = XEXP ( insn_chain, 0 );
  1123.  
  1124.         if ((( mac_insn_p ( this_insn )) ||
  1125.              ( mpy_insn_p ( this_insn ))) &&
  1126.             ( add_in == SET_DEST ( PATTERN ( this_insn ))) &&
  1127.             ( ! reg_used_between_p ( add_in, this_insn, last )))
  1128.         {
  1129.             /* kludge up: re-use existing flags, in_struct and used, 
  1130.                to inhibit the emission of normalization code at the
  1131.                front and back end of mac (and mpy) instructions. */
  1132.  
  1133.             /* turn off last's pre-norm. */
  1134.             MEM_IN_STRUCT_P ( last ) = 1;
  1135.             
  1136.             /* turn off this_insn's post-norm. */
  1137.             RTX_UNCHANGING_P ( this_insn ) = 1;
  1138.         }
  1139.         insn_chain = XEXP ( insn_chain, 1 );
  1140.         }
  1141.     }
  1142.     last = PREV_INSN ( last );
  1143.     }
  1144. }
  1145.  
  1146. /* this extraneous function is needed because the MetaWare C compiler
  1147.    can't handle the comma operator with pointer values. */
  1148.  
  1149. rtx
  1150. local_function_incoming_arg ( cum, mode, type, named )
  1151.     CUMULATIVE_ARGS cum;
  1152.     enum machine_mode mode;
  1153.     tree type;
  1154.     int named;
  1155. {
  1156.     current_func_info |= FUNC_HAS_STACK_PARMS;
  1157.  
  1158.     return FUNCTION_ARG (cum, mode, type, named);
  1159. }
  1160.  
  1161. #define N_REG_COUNT 8
  1162. #define FIRST_N_REG 6
  1163.  
  1164. static rtx current_n_reg_value[ N_REG_COUNT ];
  1165.  
  1166. void
  1167. clear_n_reg_values ( )
  1168. {
  1169.     int i = N_REG_COUNT;
  1170.     
  1171.     while ( i -- )
  1172.     {
  1173.     current_n_reg_value[i] = NULL;
  1174.     }
  1175. }
  1176.  
  1177. int
  1178. load_n_reg_p ( reg, new_value )
  1179.     rtx reg, new_value;
  1180. {
  1181.     if ( current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ] &&
  1182.     rtx_equal_p ( current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ], 
  1183.               new_value ) &&
  1184.     CONSTANT_P ( new_value ))
  1185.     {
  1186.     return 0;
  1187.     }
  1188.     else
  1189.     {
  1190.     current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ] =  new_value;
  1191.  
  1192.     return 1;
  1193.     }
  1194. }
  1195.     
  1196. /* sort the compares into the signed and unsigned varieties. */
  1197. void
  1198. sort_compares ( insns )
  1199.     rtx insns;
  1200. {
  1201.     while ( insns )
  1202.     {
  1203.     if (( INSN == GET_CODE ( insns )) &&
  1204.         ( SET == GET_CODE ( PATTERN ( insns ))) &&
  1205.         ( cc0_rtx == SET_DEST ( PATTERN ( insns ))) &&
  1206.         ( CC_UNSIGNED == next_cc_use ( insns )))
  1207.     {
  1208.         /* note that this is an unsigned (slow) compare. we must
  1209.            re-recog it in case this means we'll match a different
  1210.            insn. making the insn code -1 ensures that recog will 
  1211.            be re-run. */
  1212.         UNSIGNED_COMPARE_P ( insns ) = 1;
  1213.         INSN_CODE ( insns ) = -1;
  1214.     }
  1215.     insns = NEXT_INSN ( insns );
  1216.     }
  1217. }
  1218.  
  1219. char*
  1220. move_singleword ( operands )
  1221.     rtx *operands;
  1222. {
  1223.     extern char mem_space;
  1224.     
  1225.     if (( rtx_equal_p ( operands[0], operands[1] )) &&
  1226.     (( REG != GET_CODE ( operands[0] )) ||
  1227.      ( ! MEM_IN_STRUCT_P ( operands[0] ))) &&
  1228.     (( REG != GET_CODE ( operands[1] )) ||
  1229.      ( ! MEM_IN_STRUCT_P ( operands[1] ))))
  1230.     {
  1231.     /* if we're doing a nop move, return a null string. note that
  1232.        an insn could look like a nop move isasmuchas rtx_equal_p returns
  1233.        true; however the MEM_IN_STRUCT_P kludge used by alter_subreg ( )
  1234.        (final.c) may indicate a move from the LSW of a long to an int
  1235.        in the same accumulator. */
  1236.  
  1237.     return "";
  1238.     }
  1239.     
  1240.     switch ( which_alternative )
  1241.     {
  1242.     case 0:
  1243.     if ( MEM_IN_STRUCT_P ( operands[0] ) || 
  1244.         MEM_IN_STRUCT_P ( operands[1] ))
  1245.     {
  1246.         return "move    %1,%0";
  1247.     }
  1248.     else
  1249.     {
  1250.         return "tfr    %1,%0";
  1251.     }
  1252.  
  1253.     case 1:
  1254.     return "move    %e1,%0";
  1255.     
  1256.     case 2:
  1257.     if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  1258.     {
  1259.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  1260.         {
  1261.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1262.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1263.         }
  1264.         else
  1265.         {
  1266.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1267.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1268.         }
  1269.         
  1270.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1271.         {
  1272.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1273.         {
  1274.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  1275.         }
  1276.         else
  1277.         {
  1278.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  1279.         }
  1280.         }
  1281.         
  1282.         switch ( INTVAL ( operands[3] ))
  1283.         {
  1284.         case 0:
  1285.         RETURN_DSP ( "move    %e1,@:(%2)" );
  1286.             
  1287.         case 1:
  1288.         if ( REGNO ( operands[2] ) != REGNO ( operands[1] ))
  1289.         {
  1290.             RETURN_DSP ( "move    (%2)+\n\tmove    %e1,@:(%2)-" );
  1291.         }
  1292.             
  1293.         case -1:
  1294.         if ( REGNO ( operands[2] ) != REGNO ( operands[1] ))
  1295.         {
  1296.             RETURN_DSP ( "move    (%2)-\n\tmove    %e1,@:(%2)+" );
  1297.         }
  1298.         
  1299.         default:
  1300.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1301.         {
  1302.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  1303.         }
  1304.         else
  1305.         {
  1306.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  1307.         }
  1308.         }
  1309.     }
  1310.     else
  1311.     {
  1312.         return "move    %e1,%f0";
  1313.     }
  1314.     
  1315.     case 3:
  1316.     if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  1317.     {
  1318.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  1319.         {
  1320.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1321.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1322.         }
  1323.         else
  1324.         {
  1325.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1326.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1327.         }
  1328.         
  1329.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1330.         {
  1331.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1332.         {
  1333.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  1334.         }
  1335.         else
  1336.         {
  1337.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  1338.         }
  1339.         }
  1340.         
  1341.         switch ( INTVAL ( operands[3] ))
  1342.         {
  1343.         case 0:
  1344.         RETURN_DSP ( "move    @:(%2),%0" );
  1345.             
  1346.         case 1:
  1347.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  1348.         {
  1349.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0" );
  1350.         }
  1351.             
  1352.         case -1:
  1353.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  1354.         {
  1355.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)+,%0" );
  1356.         }
  1357.         
  1358.         default:
  1359.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1360.         {
  1361.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  1362.         }
  1363.         else
  1364.         {
  1365.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  1366.         }
  1367.         }
  1368.     }
  1369.     else
  1370.     {
  1371.         return "move    %f1,%0";
  1372.     }
  1373.     
  1374.     case 4:
  1375.     if ( 0 == INTVAL ( operands[1] ))
  1376.     {
  1377.         if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
  1378.         {
  1379.         return "clr    %0";
  1380.         }
  1381.         else
  1382.         {
  1383.         return "move    #%c1,%0";
  1384.         }
  1385.     }
  1386.     else
  1387.     {
  1388.         return "move    #>%q1,%0";
  1389.     }
  1390.     }
  1391. }
  1392.  
  1393. char*
  1394. move_doubleword ( is_float_p, operands )
  1395.     int is_float_p;
  1396.     rtx *operands;
  1397. {
  1398.     extern char mem_space;
  1399.     extern union real_extract adjusted_dval;
  1400.  
  1401.     if ( rtx_equal_p ( operands[0], operands[1] ))
  1402.     {
  1403.     return "";
  1404.     }
  1405.     
  1406.     switch ( which_alternative )
  1407.     {
  1408.     case 0:
  1409.     if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1410.     {
  1411.         if ( MEM_IN_STRUCT_P ( operands[0] )  ||
  1412.         MEM_IN_STRUCT_P ( operands[1] ))
  1413.         {
  1414.         return "move    %g1,%0\n\tmove    %1,%h0";
  1415.         }
  1416.         else
  1417.         {
  1418.         return "tfr    %g1,%0\n\tmove    %1,%h0";
  1419.         }
  1420.     }
  1421.     else
  1422.     {
  1423.         if ( MEM_IN_STRUCT_P ( operands[0] )  ||
  1424.         MEM_IN_STRUCT_P ( operands[1] ))
  1425.         {
  1426.         return "move    %1,%0";
  1427.         }
  1428.         else
  1429.         {
  1430.         return "tfr    %1,%0";
  1431.         }
  1432.     }
  1433.  
  1434.     case 1:
  1435.     if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1436.     {
  1437.         return "move    %g1,%g0\n\tmove    %1,%0";
  1438.     }
  1439.     else
  1440.     {
  1441.         return "move    %e1,%g0\n\tmove    %h1,%0";
  1442.     }
  1443.  
  1444.     case 2:
  1445.     if ( 'l' == memory_model )
  1446.     {
  1447.         if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  1448.         {
  1449.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  1450.         {
  1451.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1452.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1453.         }
  1454.         else
  1455.         {
  1456.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1457.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1458.         }
  1459.         
  1460.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1461.         {
  1462.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1463.             {
  1464.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1465.             {
  1466.                 return "move    #%p3,%j2\n\tmove    %m1,l:(%2+%j2)";
  1467.             }
  1468.             else
  1469.             {
  1470.                 return "move    %m1,l:(%2+%j2)";
  1471.             }
  1472.             }
  1473.             else
  1474.             {
  1475.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1476.             {
  1477.                 return "move    #%p3,%j2\n\tmove    %o1,l:(%2+%j2)";
  1478.             }
  1479.             else
  1480.             {
  1481.                 return "move    %o1,l:(%2+%j2)";
  1482.             }
  1483.             }
  1484.         }
  1485.         
  1486.         switch ( INTVAL ( operands[3] ))
  1487.         {
  1488.         case 0:
  1489.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1490.             {
  1491.             return "move    %m1,l:(%2)";
  1492.             }
  1493.             else
  1494.             {
  1495.             return "move    %o1,l:(%2)";
  1496.             }
  1497.             
  1498.         case 1:
  1499.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1500.             {
  1501.             return "move    (%2)+\n\tmove    %m1,l:(%2)-";
  1502.             }
  1503.             else
  1504.             {
  1505.             return "move    (%2)+\n\tmove    %o1,l:(%2)-";
  1506.             }
  1507.             
  1508.         case -1:
  1509.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1510.             {
  1511.             return "move    (%2)-\n\tmove    %m1,l:(%2)+";
  1512.             }
  1513.             else
  1514.             {
  1515.             return "move    (%2)-\n\tmove    %o1,l:(%2)+";
  1516.             }
  1517.             
  1518.         default:
  1519.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1520.             {
  1521.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1522.             {
  1523.                 return "move    #%p3,%j2\n\tmove    %m1,l:(%2+%j2)";
  1524.             }
  1525.             else
  1526.             {
  1527.                 return "move    %m1,l:(%2+%j2)";
  1528.             }
  1529.             }
  1530.             else
  1531.             {
  1532.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1533.             {
  1534.                 return "move    #%p3,%j2\n\tmove    %o1,l:(%2+%j2)";
  1535.             }
  1536.             else
  1537.             {
  1538.                 return "move    %o1,l:(%2+%j2)";
  1539.             }
  1540.             }
  1541.         }
  1542.         }
  1543.         else
  1544.         {
  1545.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1546.         {
  1547.             return "move    %m1,%f0";
  1548.         }
  1549.         else
  1550.         {
  1551.             return "move    %o1,%f0";
  1552.         }
  1553.         }
  1554.     }
  1555.     else /* memory_model is x or y. */
  1556.     {
  1557.         if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  1558.         {
  1559.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  1560.         {
  1561.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1562.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1563.         }
  1564.         else
  1565.         {
  1566.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1567.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1568.         }
  1569.         
  1570.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1571.         {
  1572.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1573.             {
  1574.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1575.             {
  1576.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1577.             }
  1578.             else
  1579.             {
  1580.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1581.             }
  1582.             }
  1583.             else
  1584.             {
  1585.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1586.             {
  1587.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1588.             }
  1589.             else
  1590.             {
  1591.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1592.             }
  1593.             }
  1594.         }
  1595.         
  1596.         switch ( INTVAL ( operands[3] ))
  1597.         {
  1598.         case 0:
  1599.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1600.             {
  1601.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)-" );
  1602.             }
  1603.             else
  1604.             {
  1605.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-" );
  1606.             }
  1607.             
  1608.         case 1:
  1609.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1610.             {
  1611.             RETURN_DSP ( "move    (%2)+\n\tmove    %1,@:(%2)+\n\tmove    %g1,@:(%2)-\n\tmove    (%2)-" );
  1612.             }
  1613.             else
  1614.             {
  1615.             RETURN_DSP ( "move    (%2)+\n\tmove    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-\n\tmove    (%2)-" );
  1616.             }
  1617.             
  1618.         case -1:
  1619.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1620.             {
  1621.             RETURN_DSP ( "move    (%2)-\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)+\n\tmove    (%2)+" );
  1622.             }
  1623.             else
  1624.             {
  1625.             RETURN_DSP ( "move    (%2)-\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)+\n\tmove    (%2)+" );
  1626.             }
  1627.             
  1628.         default:
  1629.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1630.             {
  1631.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1632.             {
  1633.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1634.             }
  1635.             else
  1636.             {
  1637.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1638.             }
  1639.             }
  1640.             else
  1641.             {
  1642.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1643.             {
  1644.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1645.             }
  1646.             else
  1647.             {
  1648.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1649.             }
  1650.             }
  1651.         }
  1652.         }
  1653.         else if ( POST_INC == GET_CODE ( XEXP ( operands[0], 0 )))
  1654.         {
  1655.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1656.         
  1657.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1658.         {
  1659.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)+" );
  1660.         }
  1661.         else
  1662.         {
  1663.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)+" );
  1664.         }
  1665.         }
  1666.         else if ( POST_DEC == GET_CODE ( XEXP ( operands[0], 0 )))
  1667.         {
  1668.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1669.         
  1670.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1671.         {
  1672.             if ( load_n_reg_p ( operands[2], 
  1673.                        gen_rtx ( CONST_INT, VOIDmode, 3 )))
  1674.             {
  1675.             RETURN_DSP ( "move    #3,%j2\n\tmove    %1,@:(%2)+\n\tmove    %g1,@:(%2)-%j2" );
  1676.             }
  1677.             else
  1678.             {
  1679.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)-%j2" );
  1680.             }
  1681.         }
  1682.         else
  1683.         {
  1684.             if ( load_n_reg_p ( operands[2], 
  1685.                        gen_rtx ( CONST_INT, VOIDmode, 3 )))
  1686.             {
  1687.             RETURN_DSP ( "move    #3,%j2\n\tmove    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-%j2" );
  1688.             }
  1689.             else
  1690.             {
  1691.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-%j2" );
  1692.             }
  1693.         }
  1694.         }
  1695.         else if ( REG == GET_CODE ( XEXP ( operands[0], 0 )))
  1696.         {
  1697.         operands[2] = XEXP ( operands[0], 0 );
  1698.         
  1699.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1700.         {
  1701.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)-" );
  1702.         }
  1703.         else
  1704.         {
  1705.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-" );
  1706.         }
  1707.         }
  1708.         else
  1709.         {
  1710.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1711.         {
  1712.             return "move    %1,%f0\n\tmove    %g1,%f0+1";
  1713.         }
  1714.         else
  1715.         {
  1716.             return "move    %h1,%f0\n\tmove    %e1,%f0+1";
  1717.         }
  1718.         }
  1719.     }
  1720.     
  1721.     case 3:
  1722.     if ( 'l' == memory_model )
  1723.     {
  1724.         if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  1725.         {
  1726.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  1727.         {
  1728.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1729.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1730.         }
  1731.         else
  1732.         {
  1733.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1734.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1735.         }
  1736.         
  1737.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1738.         {
  1739.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1740.             {
  1741.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1742.             {
  1743.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%m0";
  1744.             }
  1745.             else
  1746.             {
  1747.                 return "move    l:(%2+%j2),%m0";
  1748.             }
  1749.             }
  1750.             else
  1751.             {
  1752.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1753.             {
  1754.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%0";
  1755.             }
  1756.             else
  1757.             {
  1758.                 return "move    l:(%2+%j2),%0";
  1759.             }
  1760.             }
  1761.         }
  1762.         
  1763.         switch ( INTVAL ( operands[3] ))
  1764.         {
  1765.         case 0:
  1766.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1767.             {
  1768.             return "move    l:(%2),%m0";
  1769.             }
  1770.             else
  1771.             {
  1772.             return "move    l:(%2),%0";
  1773.             }
  1774.             
  1775.         case 1:
  1776.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1777.             {
  1778.             return "move    (%2)+\n\tmove    l:(%2)-,%m0";
  1779.             }
  1780.             else
  1781.             {
  1782.             return "move    (%2)+\n\tmove    l:(%2)-,%0";
  1783.             }
  1784.             
  1785.         case -1:
  1786.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1787.             {
  1788.             return "move    (%2)-\n\tmove    l:(%2)+,%m0";
  1789.             }
  1790.             else
  1791.             {
  1792.             return "move    (%2)-\n\tmove    l:(%2)+,%0";
  1793.             }
  1794.             
  1795.         default:
  1796.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1797.             {
  1798.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1799.             {
  1800.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%m0";
  1801.             }
  1802.             else
  1803.             {
  1804.                 return "move    l:(%2+%j2),%m0";
  1805.             }
  1806.             }
  1807.             else
  1808.             {
  1809.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1810.             {
  1811.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%0";
  1812.             }
  1813.             else
  1814.             {
  1815.                 return "move    l:(%2+%j2),%0";
  1816.             }
  1817.             }
  1818.         }
  1819.         }
  1820.         else
  1821.         {
  1822.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1823.         {
  1824.             return "move    %f1,%m0";
  1825.         }
  1826.         else
  1827.         {
  1828.             return "move    %f1,%0";
  1829.         }
  1830.         }
  1831.     }
  1832.     else /* memory_model is x or y */
  1833.     {
  1834.         if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  1835.         {
  1836.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  1837.         {
  1838.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1839.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1840.         }
  1841.         else
  1842.         {
  1843.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1844.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1845.         }
  1846.         
  1847.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1848.         {
  1849.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1850.             {
  1851.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1852.             {
  1853.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1854.             }
  1855.             else
  1856.             {
  1857.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1858.             }
  1859.             }
  1860.             else
  1861.             {
  1862.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1863.             {
  1864.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1865.             }
  1866.             else
  1867.             {
  1868.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1869.             }
  1870.             }
  1871.         }
  1872.         
  1873.         switch ( INTVAL ( operands[3] ))
  1874.         {
  1875.         case 0:
  1876.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1877.             {
  1878.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2),%0" );
  1879.             }
  1880.             else
  1881.             {
  1882.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2),%h0" );
  1883.             }
  1884.             
  1885.         case 1:
  1886.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1887.             {
  1888.             RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-,%0" );
  1889.             }
  1890.             else
  1891.             {
  1892.             RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-,%h0" );
  1893.             }
  1894.             
  1895.         case -1:
  1896.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1897.             {
  1898.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)+,%0\n\tmove    (%2)+" );
  1899.             }
  1900.             else
  1901.             {
  1902.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)+,%h0\n\tmove    (%2)+" );
  1903.             }
  1904.             
  1905.         default:
  1906.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1907.             {
  1908.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1909.             {
  1910.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1911.             }
  1912.             else
  1913.             {
  1914.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1915.             }
  1916.             }
  1917.             else
  1918.             {
  1919.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1920.             {
  1921.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1922.             }
  1923.             else
  1924.             {
  1925.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1926.             }
  1927.             }
  1928.         }
  1929.         }
  1930.         else if ( POST_INC == GET_CODE ( XEXP ( operands[1], 0 )))
  1931.         {
  1932.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1933.         
  1934.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1935.         {
  1936.             if ( load_n_reg_p ( operands[2], 
  1937.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1938.             {
  1939.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)+%j2,%0" );
  1940.             }
  1941.             else
  1942.             {
  1943.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)+%j2,%0" );
  1944.             }
  1945.         }
  1946.         else
  1947.         {
  1948.             if ( load_n_reg_p ( operands[2], 
  1949.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1950.             {
  1951.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)+%j2,%h0" );
  1952.             }
  1953.             else
  1954.             {
  1955.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)+%j2,%h0" );
  1956.             }
  1957.         }
  1958.         }
  1959.         else if ( POST_DEC == GET_CODE ( XEXP ( operands[1], 0 )))
  1960.         {
  1961.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1962.         
  1963.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1964.         {
  1965.             if ( load_n_reg_p ( operands[2], 
  1966.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1967.             {
  1968.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1969.             }
  1970.             else
  1971.             {
  1972.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1973.             }
  1974.         }
  1975.         else
  1976.         {
  1977.             if ( load_n_reg_p ( operands[2], 
  1978.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1979.             {
  1980.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1981.             }
  1982.             else
  1983.             {
  1984.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1985.             }
  1986.         }
  1987.         }
  1988.         else if ( REG == GET_CODE ( XEXP ( operands[1], 0 )))
  1989.         {
  1990.         operands[2] = XEXP ( operands[1], 0 );
  1991.         
  1992.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1993.         {
  1994.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2),%0" );
  1995.         }
  1996.         else
  1997.         {
  1998.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2),%h0" );
  1999.         }
  2000.         }
  2001.         else
  2002.         {
  2003.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2004.         {
  2005.             return "move    %f1+1,%g0\n\tmove    %f1,%0";
  2006.         }
  2007.         else
  2008.         {
  2009.             return "move    %f1+1,%0\n\tmove    %f1,%h0";
  2010.         }
  2011.         }
  2012.     }
  2013.     
  2014.     case 4:
  2015.     if ( is_float_p )
  2016.     {
  2017.         union real_extract* watcom_stink =
  2018.         (union real_extract*) &CONST_DOUBLE_LOW ( operands[1] );
  2019.         
  2020.         dtok ( NULL, watcom_stink->d );
  2021.             
  2022.         operands[2] =
  2023.         gen_rtx ( CONST_INT, VOIDmode, adjusted_dval.i[1] );
  2024.     
  2025.         operands[3] = 
  2026.         gen_rtx ( CONST_INT, VOIDmode, adjusted_dval.i[0] );
  2027.         
  2028.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2029.         {
  2030.         return "move    #>%q2,%g0\n\tmove    #>%q3,%0";
  2031.         }
  2032.         else
  2033.         {
  2034.         if ( 0 == INTVAL ( operands[3] ))
  2035.         {
  2036.             if ( 0 == INTVAL ( operands[2] ))
  2037.             {
  2038.             return "clr    %0";
  2039.             }
  2040.             else
  2041.             {
  2042.             return "move    #>%q2,%0";
  2043.             }
  2044.         }
  2045.         else
  2046.         {
  2047.             return "move    #>%q2,%0\n\tmove    #>%q3,%h0";
  2048.         }
  2049.         }
  2050.     }
  2051.     else /* not a floating constant. */
  2052.     {
  2053.         if ( CONST_INT == GET_CODE ( operands[1] ))
  2054.         {
  2055.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2056.         {
  2057.             if ( 0 == INTVAL ( operands[1] ))
  2058.             {
  2059.             return "move    #0,%g0\n\tmove    #%c1,%0";
  2060.             }
  2061.             else if ( 0 > INTVAL ( operands[1] ))
  2062.             {
  2063.             return "move    #-1,%g0\n\tmove    #>%q1,%0";
  2064.             }
  2065.             else
  2066.             {
  2067.             return "move    #0,%g0\n\tmove    #>%q1,%0";
  2068.             }
  2069.         }
  2070.         else
  2071.         {
  2072.             if ( 0 == INTVAL ( operands[1] ))
  2073.             {
  2074.             return "clr    %0";
  2075.             }
  2076.             else if ( 0 > INTVAL ( operands[1] ))
  2077.             {
  2078.             return "move    #-1,%0\n\tmove    #>%q1,%h0";
  2079.             }
  2080.             else
  2081.             {
  2082.             return "move    #0,%0\n\tmove    #>%q1,%h0";
  2083.             }
  2084.         }
  2085.         }
  2086.         
  2087.         operands[2] =
  2088.         gen_rtx ( CONST_INT, VOIDmode, 
  2089.              (( CONST_DOUBLE_LOW ( operands[1] ) >> 24 ) & 0x0000ff ) |
  2090.              (( CONST_DOUBLE_HIGH ( operands[1] ) << 8 ) & 0xffff00 ));
  2091.         operands[3] = 
  2092.         gen_rtx ( CONST_INT, VOIDmode,
  2093.              ( CONST_DOUBLE_LOW ( operands[1] ) & 0xffffff ));
  2094.         
  2095.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2096.         {
  2097.         if ( rtx_equal_p ( operands[2], operands[3] ))
  2098.         {
  2099.             return "move    #>%q2,%g0\n\tmove    %g0,%0";
  2100.         }
  2101.         else
  2102.         {
  2103.             return "move    #>%q2,%g0\n\tmove    #>%q3,%0";
  2104.         }
  2105.         }
  2106.         else
  2107.         {
  2108.         if ( 0 == INTVAL ( operands[3] ))
  2109.         {
  2110.             if ( 0 == INTVAL ( operands[2] ))
  2111.             {
  2112.             return "clr    %0";
  2113.             }
  2114.             else
  2115.             {
  2116.             return "move    #>%q2,%0";
  2117.             }
  2118.         }
  2119.         else
  2120.         {
  2121.             if ( rtx_equal_p ( operands[2], operands[3] ))
  2122.             {
  2123.             return "move    #>%q2,%0\n\tmove    %0,%h0";
  2124.             }
  2125.             else
  2126.             {
  2127.             return "move    #>%q2,%0\n\tmove    #>%q3,%h0";
  2128.             }
  2129.         }
  2130.         }
  2131.     }
  2132.     }
  2133. }
  2134.  
  2135. char*
  2136. move_pointer ( operands )
  2137.     rtx *operands;
  2138. {
  2139.     extern char mem_space;
  2140.     
  2141.     if ( rtx_equal_p ( operands[0], operands[1] ))
  2142.     {
  2143.     return "";
  2144.     }
  2145.     
  2146.     switch ( which_alternative )
  2147.     {
  2148.     case 0:
  2149.     if ( MEM_IN_STRUCT_P ( operands[0] ) || 
  2150.         MEM_IN_STRUCT_P ( operands[1] ))
  2151.     {
  2152.         return "move    %1,%0";
  2153.     }
  2154.     else
  2155.     {
  2156.         return "tfr    %1,%0";
  2157.     }
  2158.  
  2159.     case 1:
  2160.     return "move    %e1,%0";
  2161.     
  2162.     case 2:
  2163.     if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  2164.     {
  2165.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  2166.         {
  2167.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  2168.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  2169.         }
  2170.         else
  2171.         {
  2172.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  2173.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  2174.         }
  2175.         
  2176.         if ( CONST_INT != GET_CODE ( operands[3] ))
  2177.         {
  2178.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2179.         {
  2180.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  2181.         }
  2182.         else
  2183.         {
  2184.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  2185.         }
  2186.         }
  2187.         
  2188.         switch ( INTVAL ( operands[3] ))
  2189.         {
  2190.         case 0:
  2191.         RETURN_DSP ( "move    %e1,@:(%2)" );
  2192.             
  2193.         case 1:
  2194.         if ( REGNO ( operands[1] ) != REGNO ( operands[2] ))
  2195.         {
  2196.             RETURN_DSP ( "move    (%2)+\n\tmove    %e1,@:(%2)-" );
  2197.         }
  2198.             
  2199.         case -1:
  2200.         if ( REGNO ( operands[1] ) != REGNO ( operands[2] ))
  2201.         {
  2202.             RETURN_DSP ( "move    (%2)-\n\tmove    %e1,@:(%2)+" );
  2203.         }
  2204.         
  2205.         default:
  2206.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2207.         {
  2208.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  2209.         }
  2210.         else
  2211.         {
  2212.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  2213.         }
  2214.         }
  2215.     }
  2216.     else
  2217.     {
  2218.         return "move    %e1,%f0";
  2219.     }
  2220.     
  2221.     case 3:
  2222.     if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  2223.     {
  2224.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  2225.         {
  2226.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  2227.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  2228.         }
  2229.         else
  2230.         {
  2231.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  2232.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  2233.         }
  2234.         
  2235.         if ( CONST_INT != GET_CODE ( operands[3] ))
  2236.         {
  2237.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2238.         {
  2239.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  2240.         }
  2241.         else
  2242.         {
  2243.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  2244.         }
  2245.         }
  2246.         
  2247.         switch ( INTVAL ( operands[3] ))
  2248.         {
  2249.         case 0:
  2250.         RETURN_DSP ( "move    @:(%2),%0" );
  2251.             
  2252.         case 1:
  2253.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  2254.         {
  2255.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0" );
  2256.         }
  2257.             
  2258.         case -1:
  2259.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  2260.         {
  2261.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)+,%0" );
  2262.         }
  2263.         
  2264.         default:
  2265.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2266.         {
  2267.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  2268.         }
  2269.         else
  2270.         {
  2271.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  2272.         }
  2273.         }
  2274.     }
  2275.     else
  2276.     {
  2277.         return "move    %f1,%0";
  2278.     }
  2279.     
  2280.     case 4:
  2281.     if ( 0 == INTVAL ( operands[1] ) ||
  2282.         ADDR_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
  2283.     {
  2284.         if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
  2285.         {
  2286.         return "clr    %0";
  2287.         }
  2288.         else
  2289.         {
  2290.         return "move    #%c1,%0";
  2291.         }
  2292.     }
  2293.     else
  2294.     {
  2295.         return "move    #>%c1,%0";
  2296.     }
  2297.     }
  2298. }
  2299.  
  2300. #if 0
  2301. int
  2302. local_constant_address_p ( x )
  2303.     rtx x;
  2304. {
  2305.     static int found_label_or_symbol_p ( );
  2306.     
  2307.     switch ( GET_CODE ( x ))
  2308.     {
  2309.     case LABEL_REF:
  2310.     case SYMBOL_REF:
  2311.     return 1;
  2312.  
  2313.     case CONST:
  2314.     return found_label_or_symbol_p ( XEXP ( x, 0 ));
  2315.  
  2316.     default:
  2317.     return 0;
  2318.     }
  2319. }
  2320.  
  2321. static int
  2322. found_label_or_symbol_p ( x )
  2323.     rtx x;
  2324. {
  2325.     if (( LABEL_REF == GET_CODE ( x )) || ( SYMBOL_REF == GET_CODE ( x )))
  2326.     {
  2327.     return 1;
  2328.     }
  2329.     else
  2330.     { 
  2331.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2332.     
  2333.     p = fmt;
  2334.  
  2335.     while ( 'e' == *p )
  2336.     {
  2337.         if ( found_label_or_symbol_p ( XEXP ( x, p - fmt )))
  2338.         {
  2339.         return 1;
  2340.         }
  2341.         ++ p;
  2342.     }
  2343.     }
  2344.     return 0;
  2345. }
  2346. #endif
  2347.  
  2348. /* the following is a lot of bullshit to ensure that constants in the 
  2349.    assembly output *in no way* ever assume that the assembler will discard
  2350.    the carry from arithmetic operations on constants. */
  2351.  
  2352. static rtx ensure_signed_pointer_offsets ( );
  2353. static rtx ensure_signed_int_offsets ( );
  2354. static int find_symbol ( );
  2355.  
  2356. rtx
  2357. ensure_pointer_result_size ( x )
  2358.     rtx x;
  2359. {
  2360.     int mask = (~((-1) << POINTER_SIZE ));
  2361.     
  2362.     if ( CONST_INT == GET_CODE ( x ))
  2363.     {
  2364.     INTVAL ( x ) &= mask;
  2365.     }
  2366.     else if ( find_symbol ( x ))
  2367.     {
  2368.     x = ensure_signed_pointer_offsets ( x );
  2369.     }
  2370.     else
  2371.     {
  2372.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2373.     
  2374.     p = fmt;
  2375.     
  2376.     while ( '\0' != ( *p ))
  2377.     {
  2378.         if ( 'e' == ( *p ))
  2379.         {
  2380.         XEXP ( x, p - fmt ) =
  2381.             ensure_pointer_result_size ( XEXP ( x, p - fmt ));
  2382.         }
  2383.         ++ p;
  2384.     }
  2385.     }
  2386.     return x;
  2387. }
  2388.  
  2389. rtx
  2390. ensure_integer_result_size ( x )
  2391.     rtx x;
  2392. {
  2393.     int mask = (~((-1) << BITS_PER_UNIT ));
  2394.  
  2395.     if ( CONST_INT == GET_CODE ( x ))
  2396.     {
  2397.     INTVAL ( x ) &= mask;
  2398.     }
  2399.     else if ( find_symbol ( x ))
  2400.     {
  2401.     x = ensure_signed_int_offsets ( x );
  2402.     }
  2403.     else
  2404.     {
  2405.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2406.     
  2407.     p = fmt;
  2408.     
  2409.     while ( '\0' != ( *p ))
  2410.     {
  2411.         if ( 'e' == ( *p ))
  2412.         {
  2413.         XEXP ( x, p - fmt ) = 
  2414.             ensure_integer_result_size ( XEXP ( x, p - fmt ));
  2415.         }
  2416.         ++ p;
  2417.     }
  2418.     }
  2419.     return x;
  2420. }
  2421.  
  2422. static rtx
  2423. ensure_signed_pointer_offsets ( x )
  2424.     rtx x;
  2425. {
  2426.     if ( CONST_INT == GET_CODE ( x ))
  2427.     {
  2428.      INTVAL ( x ) = (( INTVAL ( x ) << ( HOST_BITS_PER_INT - POINTER_SIZE ))
  2429.              >> ( HOST_BITS_PER_INT - POINTER_SIZE ));
  2430.     }
  2431.     else
  2432.     {
  2433.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2434.     
  2435.     p = fmt;
  2436.     
  2437.     while ( '\0' != ( *p ))
  2438.     {
  2439.         if ( 'e' == ( *p ))
  2440.         {
  2441.         XEXP ( x, p - fmt ) =
  2442.             ensure_signed_pointer_offsets ( XEXP ( x, p - fmt ));
  2443.         }
  2444.         ++ p;
  2445.     }
  2446.     }
  2447.     return x;
  2448. }
  2449.  
  2450. static rtx
  2451. ensure_signed_int_offsets ( x )
  2452.     rtx x;
  2453. {
  2454.     if ( CONST_INT == GET_CODE ( x ))
  2455.     {
  2456.      INTVAL ( x ) =(( INTVAL ( x ) << ( HOST_BITS_PER_INT - BITS_PER_UNIT ))
  2457.                >> ( HOST_BITS_PER_INT - BITS_PER_UNIT ));
  2458.     }
  2459.     else
  2460.     {
  2461.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2462.     
  2463.     p = fmt;
  2464.     
  2465.     while ( '\0' != ( *p ))
  2466.     {
  2467.         if ( 'e' == ( *p ))
  2468.         {
  2469.         XEXP ( x, p - fmt ) = 
  2470.             ensure_signed_int_offsets ( XEXP ( x, p - fmt ));
  2471.         }
  2472.         ++ p;
  2473.     }
  2474.     }
  2475.     return x;
  2476. }
  2477.  
  2478. static int
  2479. find_symbol ( x )
  2480.     rtx x;
  2481. {
  2482.     int found_symbol = 0;
  2483.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2484.  
  2485.     if ( SYMBOL_REF == GET_CODE ( x ))
  2486.     {
  2487.     return 1;
  2488.     }
  2489.     
  2490.     p = fmt;
  2491.     
  2492.     while ( '\0' != ( *p ))
  2493.     {
  2494.     if ( 'e' == ( *p ))
  2495.     {
  2496.         found_symbol |= find_symbol ( XEXP ( x, p - fmt ));
  2497.     }
  2498.     ++ p;
  2499.     }
  2500.     return found_symbol;
  2501. }
  2502.  
  2503. #include "config/dsp.c"
  2504.